package com.zack.util.multitype.file;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.io.StringWriter;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

import com.zack.util.basic.creater.BasicCreater;
import com.zack.util.collections.ListProcessing;

public class ReadAndWriteFileFromDirectory {

    private static Logger logger = Logger.getLogger(ReadAndWriteFileFromDirectory.class);

    /**
     * 把两个文件的第i行与第i行进行对比。 如果不同就提取 把不同的行全部输出到文件。
     * 
     * @param file1
     * @param file2
     */
    public static void compareFileEachLine(String file1, String file2, String newFileName) {

        List<String> line1List = ReadAndWriteFileFromDirectory.readFileAndWrtToList(file1, "");
        List<String> line2List = ReadAndWriteFileFromDirectory.readFileAndWrtToList(file2, "");
        String line1FileName = ReadAndWriteFileFromDirectory.getFileNameAndSurfixFromFilePath(file1);
        String line2FileName = ReadAndWriteFileFromDirectory.getFileNameAndSurfixFromFilePath(file2);
        StringBuilder content = new StringBuilder();
        for (int i = 0; i < line1List.size() && i < line2List.size(); i++) {
            if (!line1List.get(i).trim().equals(line2List.get(i).trim())) {
                if (line2List.get(i).trim().isEmpty()) {
                    continue;
                }
                content.append(line1FileName + ": \t" + line1List.get(i) + "\r\n");
                content.append(line2FileName + ": \t" + line2List.get(i) + "\r\n");
                content.append("\r\n\r\n");
            }
        }
        ReadAndWriteFileFromDirectory.writeStringToFile(content.toString(),
                "D:\\pinduoduo\\segment\\output\\random100分词结果\\", newFileName, ".compare");
        System.out.println("Finish.");
    }

    /**
     * 把一个文件里面凡是相同的行都去掉。
     * 
     * @param oldPath
     * @param newPath
     */
    public static void removeDuplicatedData(String oldPath, String newPath) {

        List<String> brands = ReadAndWriteFileFromDirectory.readBigFileAndWrtToList(oldPath);
        // brands = removeNosy(brands);
        System.out.println("Origin Size" + brands.size());
        List<String> newBrands = ListProcessing.reduceDuplicateFromList(brands);
        System.out.println("After Removing: " + newBrands.size());
        ReadAndWriteFileFromDirectory.writeListToFileWithFileName(newBrands, newPath);
    }

    /**
     * Create file
     * 
     * @param path
     * @param fileName
     */
    @SuppressWarnings("unused")
    private static void createFile(String path, String fileName) {
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }
        File newFile = new File(file.getAbsolutePath() + File.separator + fileName + ".xml");
        try {
            newFile.createNewFile();
        } catch (IOException e) {
            logger.error("Create file error.", e);
        }
    }

    /**
     * 把map写入到文件
     * 
     * @param phraseTypeListMap:
     *            Map<String, List<String>> 一个key 和一个 value写入一行。 例如 Map<苹果:
     *            List<手机，水果>> 这个写一行： 苹果 手机 水果
     * @param splitMark:
     *            分隔符 ， 默认分割符号是\t
     */
    public void wrtMapToFile(Map<String, List<String>> phraseTypeListMap, String splitMark, String toFilePath) {
        if (null == splitMark || splitMark.isEmpty()) {
            splitMark = "\u2001\u2001\u2001";
        }
        // Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator();
        Iterator<Map.Entry<String, List<String>>> entries = phraseTypeListMap.entrySet().iterator();
        StringBuilder stringBuilder = new StringBuilder();
        String phrase = "";
        String eachVal = "";
        while (entries.hasNext()) {
            Entry<String, List<String>> eachEntry = entries.next();
            phrase = eachEntry.getKey();
            stringBuilder.append(phrase + splitMark);
            for (int i = 0; i < eachEntry.getValue().size(); i++) {
                eachVal = eachEntry.getValue().get(i);
                if (i == eachEntry.getValue().size() - 1) {
                    stringBuilder.append(eachVal);
                } else {
                    stringBuilder.append(eachVal + splitMark);
                }
            }
            stringBuilder.append("\n");
        }
        System.out.println(stringBuilder);
        writeStringToFileWithFileName(stringBuilder.toString(), toFilePath);
    }

    /**
     * 获取制定 复制目录。 传入一个目录 A/A1/ ，传入这个目录下的某个文件例如： A/A1/doc/aaa.txt 再传入一个 B/B1/ 然后返回：
     * B/B1/doc/aaa.txt 也可以接收绝对路径。
     * 
     * @param inputDir:
     *            A/A1/
     * @param inputFilePath:
     *            A/A1/doc/aaa.txt
     * @param outputDir:
     *            B/B1/
     * @param newPostFix
     *            : tnt
     * @return B/B1/doc/aaa.tnt
     */
    public static String getFilePathFromPathAndDir(String inputDir, String inputFilePath, String outputDir,
            String newPostFix) {
        newPostFix = newPostFix.replaceAll("\\.", "");
        outputDir = outputDir.replaceAll("[\\\\|\\/]+", "\\/");
        inputDir = inputDir.replaceAll("[\\\\|\\/]+", "\\/");
        inputFilePath = inputFilePath.replaceAll("[\\\\|\\/]+", "\\/");
        String finalFilePath = "";
        System.out.println(inputFilePath);
        // 建立一个newPath对原来的进行取代。
        String tempPath[] = inputFilePath.split("([\\\\|\\/]+)");
        String fileName = tempPath[tempPath.length - 1];
        String tPath = inputFilePath.replace(fileName, "");
        String newPath = tPath.replace(inputDir, outputDir);
        String newFileName = fileName;
        if (null != newPostFix && !newPostFix.equals("") && !newPostFix.equals("")) {
            String[] t = fileName.split("[\\.]");
            // 为什么不采取替换replace的方法。。 因为会名字中包含后缀替换会出错。
            newFileName = "";
            for (int i = 0; i < t.length - 1; i++) {
                newFileName = newFileName + t[i];
            }
            newFileName = newFileName + "." + newPostFix;
        }
        finalFilePath = newPath + newFileName;
        return finalFilePath;
    }

    /**
     * 
     * 把一个字符串追加到一个指定的目录文件中， 如果该文件不存在，则新建一个再进行写入。
     * 
     * @param content
     *            需要写入的字符串
     * @param toFilePath
     *            需要写入到某个路径下文件名， 不可以为空
     *            例如W:\\zackjob\\Algorithm_structure_util\\abc.txt
     * @return
     */
    public static boolean writeListToFileWithFileName(List<String> strList, String toFilePath) {

        StringBuilder content = new StringBuilder();
        for (String str : strList) {
            content.append("\n" + str);
        }
        // System.out.println("writeStringToFile"+content);
        boolean returnFlag = false;
        if (toFilePath.isEmpty()) {
            return returnFlag;
        }
        // String writeToPath=toFilePath+newFileName+"."+fileSurfix;
        File file = new File(toFilePath);
        try {
            FileWriter fWriter = new FileWriter(file, false);// true 表示append

            BufferedWriter bw = new BufferedWriter(fWriter);
            bw.write(content.toString());
            bw.flush();
            bw.close();
            returnFlag = true;
        } catch (IOException e) {
            logger.error("Write file error in method writeListToFileWithFileName");
        }
        return returnFlag;
    }

    /**
     * 获取制定 复制目录。 传入一个目录 A/A1/ ，传入这个目录下的某个文件例如： A/A1/doc/aaa.txt 再传入一个 B/B1/ 然后返回：
     * B/B1/doc/aaa.txt 也可以接收绝对路径。
     * 
     * @param inputDir:
     *            A/A1/ 或者绝对路径
     * @param inputFilePath:
     *            A/A1/doc/aaa.txt
     * @param outputDir:
     *            B/B1/ 或者绝对路径
     * @param newPostFix
     *            : tnt
     * @return B/B1/doc/aaa.tnt 或者绝对路径
     */
    public static String getFilePathFromDirToDir(String inputDir, String inputFilePath, String outputDir,
            String newPostFix) {
        newPostFix = newPostFix.replaceAll("\\.", "");
        outputDir = outputDir.replaceAll("[\\\\|\\/]+", "\\/");
        inputDir = inputDir.replaceAll("[\\\\|\\/]+", "\\/");
        inputFilePath = inputFilePath.replaceAll("[\\\\|\\/]+", "\\/");
        String finalFilePath = "";
        System.out.println(inputFilePath);
        // 建立一个newPath对原来的进行取代。
        String tempPath[] = inputFilePath.split("([\\\\|\\/]+)");
        String fileName = tempPath[tempPath.length - 1];
        String tPath = inputFilePath.replace(fileName, "");
        String newPath = tPath.replace(inputDir, outputDir);
        String newFileName = fileName;
        if (null != newPostFix && !newPostFix.equals("") && !newPostFix.equals("")) {
            String[] t = fileName.split("[\\.]");
            // 为什么不采取替换replace的方法。。 因为会名字中包含后缀替换会出错。
            newFileName = "";
            for (int i = 0; i < t.length - 1; i++) {
                newFileName = newFileName + t[i];
            }
            newFileName = newFileName + "." + newPostFix;
        }
        finalFilePath = newPath + newFileName;
        return finalFilePath;
    }

    /**
     * read File in byte, will not change anything of the origin file, even a \n
     * 
     * @param file
     * @return
     * @throws Exception
     */
    @SuppressWarnings("unused")
    public static String getContentFromFileAllByte(File file) {
        String content = "";
        try {
            byte[] encoded = Files.readAllBytes(Paths.get(file.getAbsolutePath()));
            content = new String(encoded, "UTF-8");
        } catch (Exception e) {
        }
        return content;
    }

    /**
     * 2016 11 - 12 author: zack 采用 非加载器加载的方式
     * 
     * @param file
     * @return
     */
    public static List<String> getLineListFromFileNormal(String file) {
        List<String> lines = new ArrayList<>();
        try {
            String text = readFileToStringAllBytes(new File(file));
            for (String eachLine : text.split("(\\r\\n)|(\\n)")) {
                lines.add(eachLine);
            }

        } catch (IOException e) {
            logger.error("read file error.  ", e);
        }
        return lines;
    }

    /**
     * 2016 11 - 12 author: zack 采用 类加载资源
     * 
     * @param file
     * @return
     */
    public static List<String> getListFromFileFromResource(String file) {
        List<String> lines = new ArrayList<>();
        BufferedReader bReader = null;
        try {
            InputStream iStream = getResource(file).getInputStream();
            if (null == iStream) {
                logger.error(file + " dost not exist! Return empty list");
                return lines;
            }
            InputStreamReader iReader = new InputStreamReader(iStream, "UTF-8");
            bReader = new BufferedReader(iReader);
            String eachLine = "";
            while ((eachLine = bReader.readLine()) != null) {
                lines.add(eachLine);
            }

        } catch (IOException e) {
            logger.error("read file error.  ", e);
        } finally {
            try {
                bReader.close();
            } catch (IOException e) {
                logger.error(" Reader close error. ", e);
            }
        }
        return lines;
    }

    /**
     * get one resource from class path.
     * 
     * @param path
     * @return
     * @throws IOException
     */
    public static ClassPathResource getResource(String path) throws IOException {

        return new ClassPathResource(path);
    }
    // /**
    // * 这个是测试版，不要使用， 可能出错。
    // * @param filePath
    // * @return
    // */
    // public static String getContentFromFilePath(String filePath){
    // String content = "";
    // try {
    // InputStream inputStream = new FileInputStream(new File(filePath));
    // byte[] bs = new byte[1024*1024];
    // int count =0;
    // while((count = inputStream.read(bs))>0){
    // content = content +new String(bs, 0, count);
    //// System.out.println(counting++);
    // }
    // inputStream.close();
    //
    // } catch (Exception e) {
    // // TODO Auto-generated catch block
    // e.printStackTrace();
    // }
    // return content;
    // }
    //

    /**
     * 获取目录下 文件名 ：文件内容的 Map。 举例：有一个目录 doc/ 它里面有两个文件夹doc1/ doc2/ 另外有两个文件abc.txt
     * abc.ann 返回map<文件名， 文件里的内容> 获取指定目录的一个map， key是文件名， value是这个文件的content
     * 
     * 
     * dirPath: 表示这个目录 postFix 获取这个目录里面的什么后缀的文件， 如果后缀为 “” 或者null， 表示无论什么后缀都获取。
     * splitMarkBetLineInOneArticle: 每篇文章的每一行组合到 content1
     * 中，这时候每一行与每一行之间我们可以指定一个splitmark，例如行与行之间加一个--- recursive：
     * 我们是否采用递归的方式获取整个文件夹的所有文件。 还是仅仅获取第一层，不进行递归。 需要递归传 true， 不需要递归传入false
     * 
     * 传入一个目录地址， 获取这个目录下所有文件内容组合到一起的字符串，返回这个庞大的字符串。 可以指定是否要递归获取该目录的子目录里面
     * 每一个文件内容，也允许指定 你需要的文件的后缀。
     * 
     * @param dirPath
     * @param postFix
     * @param splitMarkBetAriticles
     * @param splitMarkBetLineInOneArticle
     * @param recursive
     */
    public static Map<String, String> getMapFromWholeDirectory(String dirPath, String postFix,
            String splitMarkBetLineInOneArticle, boolean recursive) {
        Map<String, String> fileMap = new LinkedHashMap<>();
        List<String> allFilePaths = new ArrayList<>();
        if (recursive) {
            getAllFilesPathNew(dirPath, "", allFilePaths);
        } else {
            allFilePaths = getOnlyFilesPath(dirPath, postFix);
        }
        int count = 0;
        for (String path : allFilePaths) {
            String eachContent = readBigFileAndRtContent(path, splitMarkBetLineInOneArticle);
            fileMap.put(path, eachContent);
        }
        return fileMap;
    }

    /**
     * 举例：有一个目录 doc/ 它里面有两个文件夹doc1/ doc2/ 另外有两个文件abc.txt abc.ann 其中abc.txt中写着 第一句话
     * 第二句话
     * 
     * 我们的目的是获得一个字符串，这个字符串是整个目录所有文件里面内容取出来的组合。 但是我们有以下参数 dirPath: 表示这个目录 postFix
     * 获取这个目录里面的什么后缀的文件， 如果后缀为 “” 或者null， 表示无论什么后缀都获取。 splitMarkBetLineInOneArticle:
     * 每篇文章的每一行组合到 content1 中，这时候每一行与每一行之间我们可以指定一个splitmark，例如行与行之间加一个---
     * splitMarkBetAriticles： 每篇文章我们都会先生成一个content i， 整个文件夹： content1,
     * content2....我们要把他们组合成一个大的content，同样文章与文章之间可以指定一个splitMark recursive：
     * 我们是否采用递归的方式获取整个文件夹的所有文件。 还是仅仅获取第一层，不进行递归。 需要递归传 true， 不需要递归传入false
     * 
     * 传入一个目录地址， 获取这个目录下所有文件内容组合到一起的字符串，返回这个庞大的字符串。 可以指定是否要递归获取该目录的子目录里面
     * 每一个文件内容，也允许指定 你需要的文件的后缀。
     * 
     * @param dirPath
     * @param postFix
     * @param splitMarkBetAriticles
     * @param splitMarkBetLineInOneArticle
     * @param recursive
     */
    public static String getContentFromWholeDirectory(String dirPath, String postFix,
            String splitMarkBetLineInOneArticle, String splitMarkBetAriticles, boolean recursive) {
        String content = "";
        List<String> allFilePaths = new ArrayList<>();
        if (recursive) {
            getAllFilesPathNew(dirPath, "", allFilePaths);
        } else {
            allFilePaths = getOnlyFilesPath(dirPath, postFix);
        }
        int count = 0;
        for (String path : allFilePaths) {
            System.out.println(path);
            if (count++ == allFilePaths.size() - 1) {
                content = content + readBigFileAndRtContent(path, splitMarkBetLineInOneArticle);
            } else {
                content = content + readBigFileAndRtContent(path, splitMarkBetLineInOneArticle) + splitMarkBetAriticles;
            }
        }
        return content;
    }

    /**
     * 传入文件内容， 保存的文件名以及编码方式
     * 
     * @param contentString
     * @param toFilePath
     * @param encode
     */
    public static void writeStringToFileWithFileNameByte(String contentString, String toFilePath, String encode) {

        // File outpFile=new
        // File("W:\\zackjob\\hacker\\web_Bug\\zhihu\\ZhiHu_topicTemp.html");
        File outpFile = new File(toFilePath);
        FileOutputStream outputStream = null;

        try {
            byte[] bt = contentString.getBytes(encode);
            outputStream = new FileOutputStream(outpFile);
            outputStream.write(bt);
            outputStream.close();
        } catch (Exception e) {
            // TODO: handle exception
        }

    }

    /**
     * 例如 a 是文件里的内容 然后， 传入的分数是 1. 分割符号是 tab 输出文件是 a 1 传入词典文件， 传入一个指定分数， 给每个单词赋值这个分数。
     * 同时输入 修改后存储的地址。 splitMark: 单词 和 分数中间的分割符号。
     * 
     * @param fromFileName
     *            ： 字典文件存储地址
     * @param Score：
     *            单词得分
     * @param splitMark:
     *            分割符号是一个 tab
     * @param newFilePath:
     *            新的字典文件存储地址 例如 w://abc.txt
     * @return
     */
    public static String dictScoreChange(String fromFileName, int Score, String splitMark, String newFilePath) {
        if (newFilePath.isEmpty()) {
            String fileNamwithSurfix = ReadAndWriteFileFromDirectory.getFileNameAndSurfixFromFilePath(fromFileName);
            String fileN = ReadAndWriteFileFromDirectory.getFileNameFromFilePath(fromFileName);
            newFilePath = fromFileName.replace(fileNamwithSurfix, "") + fileN + "_Score.txt";
        }
        // System.out.println("新文件路径："+newFilePath);
        if (newFilePath.isEmpty()) {
            splitMark = "\t";
        }

        File file = new File(fromFileName);
        BufferedReader reader = null;
        String fileString1 = "";
        try {
            reader = new BufferedReader(new FileReader(file));
            String tempString = "";
            int line = 1;
            // 写入文件
            // if file doesnt exists, then create it
            File file1 = new File(newFilePath);
            if (!file1.exists()) {
                file1.createNewFile();
            }
            FileWriter fileWriter = new FileWriter(newFilePath, true);
            BufferedWriter bw = new BufferedWriter(fileWriter);
            // 对写入文件的配置

            while ((tempString = reader.readLine()) != null) {
                // fileString1=fileString1+tempString+"\r\n";
                String tempWord = tempString + splitMark + Score + "\r\n";
                line++;
                bw.write(tempWord);
                bw.flush();

            }
            bw.close();
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }
        return fileString1;
    }

    /**
     * 传入一个html文件，和一个解码的字符集。
     * 
     * @param fileName
     *            ： 传入的文件路径 w://abc.html
     * @param encoding
     *            : 对这个文件读取的时候进行解码 例如 UTF-8
     * @return
     */
    public static String readFileWithEncodingAndReturnContent(String fileName, String encoding) {
        if (encoding.isEmpty()) {
            encoding = "UTF-8";
        }
        String contentString = "";
        File file = new File(fileName);
        try {
            InputStreamReader isR = new InputStreamReader(new FileInputStream(file), encoding);
            BufferedReader bf = new BufferedReader(isR);
            String eachLineString = "";
            while ((eachLineString = bf.readLine()) != null) {
                contentString = contentString + eachLineString + "\r\n";
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return contentString;
    }

    // 使用字节流进行读取
    public static String readFileToStringAllBytes(File file) throws IOException {
        byte[] encoded = Files.readAllBytes(Paths.get(file.getAbsolutePath()));
        return new String(encoded, "UTF-8");
    }

    /**
     * 传入一个文件的绝对路径，返回这个文件的内容
     * 
     * @param fileName
     * @return
     */
    public static String readFileAndReturnContent(String fileName, String postfix) {
        // System.out.println("readFileAndReturnContent: "+fileName);
        File file = new File(fileName);
        BufferedReader reader = null;
        String fileString1 = "";
        try {
            reader = new BufferedReader(new FileReader(file));
            String tempString = "";
            int line = 1;
            while ((tempString = reader.readLine()) != null) {
                fileString1 = fileString1 + tempString + postfix;
                line++;
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }
        return fileString1;
    }

    /**
     * 传入一个文件的绝对路径，返回这个文件的内容
     * 
     * @param fileName
     * @return
     */
    public static String readFileAndReturnContent(String fileName) {
        // System.out.println("readFileAndReturnContent: "+fileName);
        File file = new File(fileName);
        BufferedReader reader = null;
        String fileString1 = "";
        try {
            reader = new BufferedReader(new FileReader(file));
            String tempString = "";
            int line = 1;
            while ((tempString = reader.readLine()) != null) {
                fileString1 = fileString1 + tempString;
                line++;
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }
        return fileString1;
    }

    /**
     * 
     * 把一个指定文件，写入到指定目录下指定的文件中去。如果写入到的目标文件不存在，则生成一个新文件。
     * 
     * @param fromFileName
     *            需要打开的文件，要把它的内容写入别的地方去。
     *            不可以为空例如W:\\zackjob\\Algorithm_structure_util\\Heritrix_1.144\\
     *            jobs\\SohuNews-20160313000256928\\mirror\\news.sohu.com\\
     *            20130702\\n380405425.shtml
     * @param toFilePath
     *            需要写入到某个路径下， 不可以为空 例如W:\\zackjob\\Algorithm_structure_util\\
     * @param newFileName
     *            指定写入到某个文件名。可以为空，如果为空，自动以当前时间精确到毫秒为文件名
     * @param fileSurfix
     *            指定写入到文件的类型，不指定，则为txt 。 可以为空
     * @return
     */
    public static String readFileAndWriteToFile(String fromFileName, String toFilePath, String newFileName,
            String fileSurfix) {

        if (fileSurfix.isEmpty()) {
            fileSurfix = "txt";
        }
        // 如果用户没有设置文件名， 则分配一个时间给文件名。
        if (newFileName.isEmpty()) {
            newFileName = BasicCreater.getIDByTimeCalender();
        }

        toFilePath = toFilePath + newFileName + "." + fileSurfix;

        File file = new File(fromFileName);
        BufferedReader reader = null;
        String fileString1 = "";
        try {
            reader = new BufferedReader(new FileReader(file));
            String tempString = "";
            int line = 1;
            // 写入文件
            // if file doesnt exists, then create it
            File file1 = new File(toFilePath);
            if (!file1.exists()) {
                file1.createNewFile();
            }
            FileWriter fileWriter = new FileWriter(toFilePath, true);
            BufferedWriter bw = new BufferedWriter(fileWriter);
            // 对写入文件的配置

            while ((tempString = reader.readLine()) != null) {
                // fileString1=fileString1+tempString+"\r\n";
                String tempStr = tempString + "\r\n";
                line++;
                bw.write(tempStr);
                bw.flush();

            }
            bw.close();
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }
        return fileString1;
    }

    /**
     * 
     * 把一个字符串追加到一个指定的目录文件中， 如果该文件不存在，则新建一个再进行写入。
     * 
     * @param content
     *            需要写入的字符串
     * @param toFilePath
     *            需要写入到某个路径下， 不可以为空 例如W:\\zackjob\\Algorithm_structure_util\\
     * @param newFileName
     *            指定写入到某个文件名。可以为空，如果为空，自动以当前时间精确到毫秒为文件名 abc
     * @param fileSurfix
     *            指定写入到文件的类型，不指定，则为txt 。 可以为空
     * @return
     */
    public static boolean writeStringToFile(String content, String toFilePath, String newFileName, String fileSurfix) {
        // System.out.println("writeStringToFile"+content);
        boolean returnFlag = false;
        if (toFilePath.isEmpty()) {
            return returnFlag;
        }
        if (newFileName.isEmpty()) {
            newFileName = BasicCreater.getIDByTimeCalender();
        }
        if (fileSurfix.isEmpty()) {
            fileSurfix = "txt";
        }
        String writeToPath = toFilePath + newFileName + "." + fileSurfix;
        File file = new File(writeToPath);
        try {
            FileWriter fWriter = new FileWriter(file, true);// true 表示append
            BufferedWriter bw = new BufferedWriter(fWriter);

            bw.write(content);
            bw.flush();
            bw.close();
            returnFlag = true;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return returnFlag;
    }

    /**
     * 
     * 把一个字符串追加到一个指定的目录文件中， 如果该文件不存在，则新建一个再进行写入。
     * 
     * @param content
     *            需要写入的字符串
     * @param toFilePath
     *            需要写入到某个路径下文件名， 不可以为空
     *            例如W:\\zackjob\\Algorithm_structure_util\\abc.txt
     * @return
     */
    public static boolean writeStringToFileWithFileName(String content, String toFilePath) {
        // System.out.println("writeStringToFile"+content);
        boolean returnFlag = false;
        if (toFilePath.isEmpty()) {
            return returnFlag;
        }
        // String writeToPath=toFilePath+newFileName+"."+fileSurfix;
        File file = new File(toFilePath);
        try {
            FileWriter fWriter = new FileWriter(file, true);// true 表示append

            BufferedWriter bw = new BufferedWriter(fWriter);
            bw.write(content);
            bw.flush();
            bw.close();
            returnFlag = true;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return returnFlag;
    }

    /**
     * 给定一个路径，获取路径下所有文件，以及文件夹下的所有文件， 的路径集合。 返回一个ArrayList 里面是所有文件的路径名包括（文件名）
     * 
     * @param inputPath
     * @param 指定需要获取的目标文件的格式
     * @return
     */
    public static List<String> getAllFilesPathNew(String inputPath, String postfix, List<String> resultPathList1) {
        // if (String_handle_Zack_Util.isEmpty(postfix)) {
        // postfix="";
        // }
        try {
            File file = new File(inputPath);
            File[] files = file.listFiles();

            for (File f : files) {

                if (f.isDirectory()) {
                    getAllFilesPathNew(f.getAbsolutePath(), postfix, resultPathList1);// 递归获取文件绝对路径
                } else {
                    if (postfix.isEmpty()) {
                        resultPathList1.add(f.getAbsolutePath());
                    } else {
                        if (f.getName().endsWith(postfix)) {
                            resultPathList1.add(f.getAbsolutePath());
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultPathList1;
    }

    public static List<String> getAllFilesPath(String dirPath, List<String> resultPathList1) {
        try {
            File file = new File(dirPath);
            File[] files = file.listFiles();
            for (File f : files) {
                if (f.isDirectory()) {
                    getAllFilesPath(f.getAbsolutePath(), resultPathList1);// 递归获取文件绝对路径
                } else {
                    resultPathList1.add(f.getAbsolutePath());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultPathList1;
    }

    /**
     * 给定一个路径，获取路径下所有文件，以及文件夹下的所有文件， 的路径集合。 返回一个ArrayList 里面是所有文件的路径名包括（文件名）
     * 
     * @param inputPath
     * @param 指定需要获取的目标文件的格式
     * @return
     */
    @Deprecated
    public static List<String> resultPathList = new ArrayList<String>();

    @Deprecated
    public static List<String> getAllFilesPath(String inputPath, String postfix) {
        if (postfix.isEmpty()) {
            postfix = ".txt";
        }
        try {
            File file = new File(inputPath);
            File[] files = file.listFiles();

            for (File f : files) {

                if (f.isDirectory()) {
                    getAllFilesPath(f.getAbsolutePath(), postfix);// 递归获取文件绝对路径
                } else {
                    if (f.getName().endsWith(postfix)) {
                        resultPathList.add(f.getAbsolutePath());
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultPathList;
    }

    /**
     * 获取文件夹里的所有后缀文件，不递归 传入一个文件路径， 和一种指定的文件类型， 返回某个文件夹里面所有这个文件的文件地址包括文件名。
     * 注意本方法只是获取第一层目录。 而不进行递归。
     * 
     * @param inputPath
     * @param surfix
     *            用户需要获得的文件类型， 可以为null 或者为空
     * @return
     */
    public static List<String> getOnlyFilesPath(String inputPath, String surfix) {
        List<String> resultList = new ArrayList<String>();
        try {
            File file = new File(inputPath);
            File[] files = file.listFiles();
            for (File f : files) {
                if (f.isDirectory()) {
                    continue;
                } else {
                    if (surfix.isEmpty()) {
                        resultList.add(f.getAbsolutePath());
                    } else {
                        if (f.getName().endsWith(surfix)) {
                            resultList.add(f.getAbsolutePath());
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // System.out.println("1111: "+resultList.size());
        return resultList;
    }

    /**
     * 传入一个文件地址，返回这个文件的文件名包括后缀名字，可以包含中文空格和-_ //D:\BaiduYunDownload\毒枭 美剧\毒枭ab_t哈
     * 哈-1.txt 返回 毒枭ab_t哈 哈-1.txt
     * 
     * @param filePath
     * @return
     */
    public static String getFileNameAndSurfixFromFilePath(String filePath) {
        if (filePath.isEmpty()) {
            return "no file inputed";
        }
        String fileName = "";
        // String
        // regex="([A-Za-z0-9\\-]|[\u4e00-\u9fa5]*):\\\\([A-Za-z0-9-]|[\u4e00-\u9fa5]\\\\)*(.*).[0-9A-Za-z]+";
        String regex = "([0-9A-Za-z\u4e00-\u9fa5\\-_\\s]*:\\\\)([0-9A-Za-z\u4e00-\u9fa5\\-_\\s]*\\\\)*([0-9a-zA-Z\u4e00-\u9fa5\\-_\\s]*).([0-9A-Za-z]+)";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(filePath);
        if (matcher.find()) {
            fileName = matcher.group(3) + "." + matcher.group(4);
        }
        return fileName;
    }

    /**
     * 传入一个文件地址，返回这个文件的后缀名字，可以包含中文空格和-_ ////D:\BaiduYunDownload\毒枭 美剧\毒枭ab_t哈
     * 哈-1.txt 返回 .txt
     * 
     * @param filePath
     * @return
     */
    public static String getFileSurfixFromFilePath(String filePath) {
        if (filePath.isEmpty()) {
            return "no file inputed";
        }
        String fileName = "";
        // String
        // regex="([A-Za-z0-9\\-]|[\u4e00-\u9fa5]*):\\\\([A-Za-z0-9-]|[\u4e00-\u9fa5]\\\\)*(.*).[0-9A-Za-z]+";
        String regex = "([0-9A-Za-z\u4e00-\u9fa5\\-_\\s]*:\\\\)([0-9A-Za-z\u4e00-\u9fa5\\-_\\s]*\\\\)*([0-9a-zA-Z\u4e00-\u9fa5\\-_\\s]*).([0-9A-Za-z]+)";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(filePath);
        if (matcher.find()) {
            fileName = matcher.group(4);
        }
        return fileName;
    }

    /**
     * 传入一个文件地址，返回这个文件名，可以包含中文空格和-_ //D:\BaiduYunDownload\毒枭 美剧\毒枭.ab_t哈 哈-1.txt
     * 
     * @param filePath
     * @return
     */
    public static String getFileNameFromFilePath(String filePath) {
        if (null == filePath || filePath.isEmpty()) {
            return "no file inputed";
        }
        String fileName = "";
        // String
        // regex="([A-Za-z0-9\\-]|[\u4e00-\u9fa5]*):\\\\([A-Za-z0-9-]|[\u4e00-\u9fa5]\\\\)*(.*).[0-9A-Za-z]+";
        String regex = "([0-9A-Za-z\u4e00-\u9fa5\\-_\\s:]*[\\\\/]*)([0-9A-Za-z\u4e00-\u9fa5\\-_\\s]*[\\\\/]+)*([0-9a-zA-Z\u4e00-\u9fa5\\-_\\s]*).([0-9A-Za-z]+)";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(filePath);
        if (matcher.find()) {
            fileName = matcher.group(3);
        }
        return fileName;
    }

    /**
     * 传入一个文件地址， 返回一个Arraylist<String> 根据要求制定分割符号
     * 
     * @param fromPath
     *            对哪个文件进行处理
     * @param splitMark
     *            分割符号可以指定。 默认是 "\r\n"
     */
    public static List<String> readFileAndWrtToList(String fromPath, String splitMark) {
        if (splitMark == "" || splitMark == null) {
            splitMark = "\r\n";
        }
        List<String> wordList = new ArrayList<>();
        String content = "";
        try {
            File file = new File(fromPath);
            FileReader fReader = new FileReader(file);
            BufferedReader bReader = new BufferedReader(fReader);
            String tempLine = "";
            while ((tempLine = bReader.readLine()) != null) { // 先组合成整篇文章再进行分割
                content = content + tempLine + "\r\n";
            }
            String[] tempwordList = content.split(splitMark);
            for (int i = 0; i < tempwordList.length; i++) {
                wordList.add((tempwordList[i].trim()));
            }
            // System.out.println(tempwordList[0]+"========");
            // wordList=Arrays.asList(tempwordList);

            fReader.close();
            bReader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return wordList;
    }

    /**
     * 读取大文件 传入一个文件地址， 返回一个Arraylist<String> 一行一行的读取，读取一行就加入到list里面去
     * 
     * @param fromPath
     *            对哪个文件进行处理
     * @param 这个方法不指定分割符号
     */
    public static List<String> readBigFileAndWrtToList(String fromPath) {
        List<String> wordList = new ArrayList<>();
        FileInputStream inputStream = null;
        Scanner sc = null;
        try {
            try {
                inputStream = new FileInputStream(fromPath);
                sc = new Scanner(inputStream, "UTF-8");
                while (sc.hasNextLine()) {
                    String line = sc.nextLine();
                    wordList.add(line);
                }
                // note that Scanner suppresses exceptions
                if (sc.ioException() != null) {
                    throw sc.ioException();
                }
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (sc != null) {
                    sc.close();
                }
            }

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return wordList;
    }

    /**
     * 读取大文件 传入一个文件地址， 返回一个Arraylist<String> 一行一行的读取，读取一行就加入到list里面去
     * 
     * @param fromPath
     *            对哪个文件进行处理
     * @param splitMark
     *            分割符号可以指定。 默认是 ""
     */
    public static List<String> readBigFileAndWrtToList(String fromPath, String splitMark) {
        if (splitMark == "" || splitMark == null) {
            splitMark = "";
        }
        List<String> wordList = new ArrayList<>();
        String content = "";
        FileInputStream inputStream = null;
        Scanner sc = null;
        try {
            try {
                inputStream = new FileInputStream(fromPath);
                sc = new Scanner(inputStream, "UTF-8");
                while (sc.hasNextLine()) {
                    String line = sc.nextLine() + splitMark;
                    wordList.add(line);
                }
                // note that Scanner suppresses exceptions
                if (sc.ioException() != null) {
                    throw sc.ioException();
                }
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (sc != null) {
                }
            }

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return wordList;
    }

    /**
     * 读取大文件 传入一个文件地址， 返回一个Arraylist<String> 一行一行的读取，读取一行就加入到list里面去
     * 
     * @param fromPath
     *            对哪个文件进行处理
     * @param splitMark
     *            分割符号可以指定。 默认是 ""
     */
    public static String readBigFileAndRtContent(String fromPath, String splitMark) {
        if (splitMark == null) {
            splitMark = "";
        }
        String content = "";
        FileInputStream inputStream = null;
        Scanner sc = null;
        try {
            try {
                inputStream = new FileInputStream(fromPath);
                sc = new Scanner(inputStream, "UTF-8");
                while (sc.hasNextLine()) {
                    String line = sc.nextLine() + splitMark;
                    content = content + line;
                }
                // note that Scanner suppresses exceptions
                if (sc.ioException() != null) {
                    throw sc.ioException();
                }
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (sc != null) {
                    sc.close();
                }
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return content;
    }

    /**
     * 读取文件里的内容并进行返回
     * 
     * @param eachFile
     * @return
     */
    public static String readBigFileReturnContent(File eachFile) {
        // TODO Auto-generated method stub
        String content = "";
        FileInputStream inputStream = null;
        Scanner sc = null;
        try {
            inputStream = new FileInputStream(eachFile);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        sc = new Scanner(inputStream, "UTF-8");
        while (sc.hasNext()) {
            String line = sc.nextLine();
            content = content + line;
        }
        sc.close();
        return content;
    }

    /**
     * * time(default is Create Time may change)：Jan 16, 2017 11:11:42 AM 传入一个目录地址，
     * 以及一个coding 的解码方式。 例如： "UTF-8" 之类的。
     * 
     * @param filePath
     * @param coding
     * @return
     */
    public List<String> readFileByteByLineToList(String filePath, String coding, int byteSize) {
        List<String> lineList = new ArrayList<>();
        int newLineCode = 10; // 换行符
        int enterCode = 13; // 回车符
        byte[] eachLine = new byte[0];
        // String enter = "\n";
        int bufSize = 0x8000000;
        if (byteSize < 0) {
            bufSize = 0x8000000;
        } else {
            bufSize = byteSize;
        }
        String encode = "";
        if (coding.isEmpty()) {
            encode = "UTF-8";
        } else {
            encode = coding;
        }
        File inputFile = new File(filePath);
        try {
            @SuppressWarnings("resource")
            FileChannel fileChannel = new RandomAccessFile(inputFile, "r").getChannel();
            // 注意，文件通道的可读可写要建立在文件流本身可读写的基础之上
            // MappedByteBuffer out = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0,
            // bufSize);
            ByteBuffer wBuffer = ByteBuffer.allocate(bufSize);
            byte[] temp = new byte[0];
            while (fileChannel.read(wBuffer) != -1) { // 如果一次没有读完就分两次， 直到-1的时候不再读取
                int rSize = wBuffer.position();
                byte[] bs = new byte[rSize];
                wBuffer.rewind();
                wBuffer.get(bs);
                wBuffer.clear();
                int startNum = 0;
                boolean hasNewLine = false;
                for (int i = 0; i < rSize; i++) {
                    if (bs[i] == newLineCode) {
                        hasNewLine = true;
                        int tempNum = temp.length;
                        int lineNum = i - startNum;
                        eachLine = new byte[tempNum + lineNum];
                        System.arraycopy(temp, 0, eachLine, 0, tempNum);
                        temp = new byte[0];
                        System.arraycopy(bs, startNum, eachLine, tempNum, lineNum);

                        String line = new String(eachLine, 0, eachLine.length, encode);
                        lineList.add(line);
                        if (i + 1 < rSize && bs[i + 1] == enterCode) {
                            startNum = i + 2;
                        } else {
                            startNum = i + 1;
                        }
                    }
                }
                if (hasNewLine) {
                    temp = new byte[bs.length - startNum];
                    System.arraycopy(bs, startNum, temp, 0, temp.length);
                } else {// 兼容单次读取的内容不足一行的情况
                    byte[] toTemp = new byte[temp.length + bs.length];
                    System.arraycopy(temp, 0, toTemp, 0, temp.length);
                    System.arraycopy(bs, 0, toTemp, temp.length, bs.length);
                    temp = toTemp;
                }
            }
            if (temp != null && temp.length > 0) {// 兼容文件最后一行没有换行的情况
                String line = new String(temp, 0, temp.length, encode);
                lineList.add(line);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return lineList;
    }

    /**
     * * time(default is Create Time may change)：Jan 16, 2017 11:11:42 AM 传入文件路径，
     * 获取这个文件里面内容的信息。 每一行， 返回一个list<line>。
     * 
     * @param filePath
     * @return
     */
    public List<String> readFileByteByLineToList(String filePath) {
        String coding = "UTF-8";
        int byteSize = 0x8000000;
        List<String> lineList = readFileByteByLineToList(filePath, coding, byteSize);
        return lineList;
    }

    /**
     * * time(default is Create Time may change)：Jan 16, 2017 11:11:42 AM 传入文件路径，
     * 以及buffer 缓冲区的大小。 获取这个文件里面内容的信息。 每一行， 返回一个list<line>。
     * 
     * @param filePath
     * @return
     */
    public List<String> readFileByteByLineToList(String filePath, int byteSizeTemp) {
        String coding = "UTF-8";
        int byteSize = 0;
        if (byteSize < 0) {
            byteSize = 0x8000000;
        } else {
            byteSize = byteSizeTemp;
        }
        List<String> lineList = readFileByteByLineToList(filePath, coding, byteSize);
        return lineList;
    }

    /**
     * * time(default is Create Time may change)：Jan 16, 2017 11:11:42 AM 传入文件路径，
     * 以及buffer 缓冲区的大小。 获取这个文件里面内容的信息。 每一行， 返回一个list<line>。
     * 
     * @param filePath
     * @return
     */
    public List<String> readFileByteByLineToList(String filePath, String codingTemp) {
        String coding = "UTF-8";
        if (null == coding || coding.isEmpty()) {
            coding = "UTF-8";
        } else {
            coding = codingTemp;
        }
        int byteSize = 0x8000000;
        List<String> lineList = readFileByteByLineToList(filePath, coding, byteSize);
        return lineList;
    }

    /**
     * 传入一个目录, 以及两种文件后缀, 然后返回map 一一对应两个同名不同后缀的文件地址. 例如, 1.txt 1.deid 2.txt 2.deid 传入
     * txt, deid, 以及这个文件夹/home/data/, 则返回map </home/data/1.txt, /home/data/1.deid>
     * </home/data/2.txt, /home/data/2.deid>
     * 
     * @param postFix1:
     *            txt 或者.txt
     * @param postFix2:
     * @param dirPath:
     */
    public static Map<String, String> getFilePairs(String postFix1, String postFix2, String dirPath) {
        Map<String, String> filePairMaps = new LinkedHashMap<String, String>();
        List<String> fileList = new ArrayList<>();
        fileList = getAllFilesPath(dirPath, fileList);

        for (String eachFile1 : fileList) {
            if (!eachFile1.endsWith(postFix1)) {
                continue;
            }
            String newEachFile1 = getFilePathWithoutPostFix(eachFile1);
            for (String eachFile2 : fileList) {
                if (!eachFile2.endsWith(postFix2)) {
                    continue;
                }
                String newEachFile2 = getFilePathWithoutPostFix(eachFile2);
                if (newEachFile1.equals(newEachFile2)) {
                    filePairMaps.put(eachFile1, eachFile2);
                    break;
                }
            }
        }
        return filePairMaps;
    }

    /**
     * 输入一个file的路径, 返回不带后缀的路径. 例如: /home/moap/deid.data/deid001.txt 返回:
     * /home/moap/deid.data/deid001
     * 
     * @param filePath
     * @return
     */
    public static String getFilePathWithoutPostFix(String filePath) {
        String strRegex = "(\\.)[a-z0-9\\=\\+\\-]+$";
        String filePathWithoutSurfix = filePath.replaceAll(strRegex, "");
        return filePathWithoutSurfix;
    }

    /**
     * get all dir path in a directory. just get 1 depth. not recursivly.
     * 
     * @param dirPath
     * @return
     */
    public static List<String> getDirPathsFromDir(String dirPath) {
        List<String> dirPaths = new ArrayList<>();
        try {
            File file = new File(dirPath);
            File[] files = file.listFiles();
            for (File f : files) {
                if (f.isDirectory()) {
                    dirPaths.add(f.getPath() + "/");
                }
            }
        } catch (Exception e) {
            logger.error("File Read Error.");
        }
        return dirPaths;
    }
    
    /**
     * 可从jar包里加载资源。
     * @param configPath
     * @return
     */
    public static InputStream getDataInputStream(String configPath) {
        InputStream     is;
        String          path = System.getProperty("user.dir");
        File            file = new File(path + "/" + configPath);
        if (file.exists()) {
            try {
                is = new FileInputStream(file);
                //logger.info("DataLoader: open file stream from a general file: " + configPath);
                return is;
            } catch (FileNotFoundException e) {
                StringWriter writer = new StringWriter();
                e.printStackTrace(new PrintWriter(writer));
                logger.error(writer.getBuffer().toString());
                //System.err.println(writer.getBuffer().toString());
                return null;
            }
        } else {
            int     index = configPath.indexOf("/");
            String  resourcePath = configPath.substring(index + 1);
            is = ReadAndWriteFileFromDirectory.class.getClassLoader().getResourceAsStream(resourcePath);
            if (is != null) {
                //logger.info("DataLoader: open file stream from a jar package: " + configPath);
                //System.out.println("DataLoader: open file stream from a jar package: " + configPath);
            }
            else {
                logger.error("DataLoader: open file stream NOT exists: " + configPath);
                //System.err.println("DataLoader: open file stream NOT exists: " + configPath);
            }
            return is;
        }
    }

    public static List<String> getListFromInPutStream(InputStream inStram) {
        List<String> lines = new ArrayList<>();
        BufferedReader bReader = null;
        try {
            InputStream iStream = inStram;
            if (null == iStream) {
                System.out.println(" dost not exist! Return empty list ");
                return lines;
            }
            InputStreamReader iReader = new InputStreamReader(iStream, "UTF-8");
            bReader = new BufferedReader(iReader);
            String eachLine = "";
            while ((eachLine = bReader.readLine()) != null) {
                lines.add(eachLine);
            }
 
        } catch (IOException e) {
            System.out.println(" read file error. " + e);
        } finally {
            try {
                bReader.close();
            } catch (IOException e) {
                System.out.println(" Reader close error. " + e);
            }
        }
        return lines;
    }

}